{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "import sympy as sy\n",
    "sy.init_printing() "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <font face=\"gotham\" color=\"purple\">Definition of Linear Independence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If all $c$'s are zero, the set of vectors $\\{v_1, v_2,...,v_p\\}$ is said to be <font face=\"gotham\" color=\"red\">linearly independent</font>, if the equation\n",
    "\n",
    "$$c_{1} {v}_{1}+c_{2} {v}_{2}+\\cdots+c_{p} {v}_{p}=\\mathbf{0}$$\n",
    "\n",
    "holds.\n",
    "\n",
    "However if any of $c$'s are nonzero, the set of vectors is linearly dependent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font face=\"gotham\" color=\"purple\"> Example 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Determine if ${v}_1, {v}_2, {v}_3\\$ are linearly independent.\n",
    "$${v}_{1}=\\left[\\begin{array}{l}\n",
    "1 \\\\\n",
    "2 \\\\\n",
    "3\n",
    "\\end{array}\\right]^T, \n",
    "{v}_{2}=\\left[\\begin{array}{l}\n",
    "4 \\\\\n",
    "5 \\\\\n",
    "6\n",
    "\\end{array}\\right]^T, \\text { and } {v}_{3}=\\left[\\begin{array}{l}\n",
    "2 \\\\\n",
    "1 \\\\\n",
    "0\n",
    "\\end{array}\\right]^T$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The common way of testing linear combination is to "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}1 & 0 & -2 & 0\\\\0 & 1 & 1 & 0\\\\0 & 0 & 0 & 0\\end{matrix}\\right], \\  \\left( 0, \\  1\\right)\\right)$"
      ],
      "text/plain": [
       "⎛⎡1  0  -2  0⎤        ⎞\n",
       "⎜⎢           ⎥        ⎟\n",
       "⎜⎢0  1  1   0⎥, (0, 1)⎟\n",
       "⎜⎢           ⎥        ⎟\n",
       "⎝⎣0  0  0   0⎦        ⎠"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = sy.Matrix([[1,4,2,0],\n",
    "               [2,5,1,0],\n",
    "               [3,6,0,0]])\n",
    "A.rref()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The solution shows that $x_3$ is a free variable, and naturally it could be nonzero, therefore the set is linearly dependent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font face=\"gotham\" color=\"purple\"> Example 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Consider a matrix $A$， determine columns of $A$ are linearly independent.\n",
    "\n",
    "$$\n",
    "A=\\left[\\begin{array}{rrr}\n",
    "0 & 1 & 4 \\\\\n",
    "1 & 2 & -1 \\\\\n",
    "5 & 8 & 0\n",
    "\\end{array}\\right]\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solve the system via augmented matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/latex": [
       "$\\displaystyle \\left( \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\0 & 1 & 0 & 0\\\\0 & 0 & 1 & 0\\end{matrix}\\right], \\  \\left( 0, \\  1, \\  2\\right)\\right)$"
      ],
      "text/plain": [
       "⎛⎡1  0  0  0⎤           ⎞\n",
       "⎜⎢          ⎥           ⎟\n",
       "⎜⎢0  1  0  0⎥, (0, 1, 2)⎟\n",
       "⎜⎢          ⎥           ⎟\n",
       "⎝⎣0  0  1  0⎦           ⎠"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = sy.Matrix([[0,1,4,0],[1,2,-1,0],[5,8,0,0]])\n",
    "A.rref()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$Ax=0$ has only trivial solution, so the columns of $A$ are linearly independent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Linear independence is closly connected with linear combination, in next section we visualize the linear independence."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <font face=\"gotham\" color=\"purple\"> Visualization of Linear Independence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's take a look an exmaple in $\\mathbb{R}^2$, show $(3, 2)^T$, $(-9, -6)^T$, $(6, 4)^T$ are linearly dependent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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FYUJERERiYrChIiIiERFYUJERESiojAhIiIiUVGYEBERkagoTIiIiEhUFCZEREQkKgoTIiIiEhWFCREREYmKwoSIiIhERWFCREREoqIwISIiIlFRmBAREZGoKEyIiIhIVBQmREREJCoKEyIiIhIVhQkRERGJisKEiIiIREVhQkRERKKiMCEiIiJRUZgQERGRqChMiIiISFQUJkRERCQqChMiIiISFYUJERERiYrChIiIiEQlKcOEmRWY2UeVvjaa2ZVV9ik0s28r7XNTouoVERFJZRmJLmBXuPsCoAOAmaUDK4AXw+z6jrufEc/aREREGpuk7ExU0RX43N2XJroQERGRxsjcPdE1RMXMRgMz3f2BKq8XAv8AlgMrgWvc/dMw7x8ODAfIz8/vNGHChHqvOVGKi4vJy8tLdBn1IpXPDXR+yU7nl7xS+dwAioqKZrj7cdEeJ6nDhJllEQSFI939qyrbdgMq3L3YzHoC97n7oTUdr6CgwBcsWFB/BSfY5MmTKSwsTHQZ9SKVzw10fslO55e8UvncAMwsJmEi2S9z/JSgK/FV1Q3uvtHdi0OPXwUyzWyfeBcoIiKS6pI9TAwAngm3wcxamJmFHncmONd1caxNRESkUUjKuzkAzCwXOB24pNJrlwK4+9+AfsBlZlYGbAXO82S+piMiItJAJW2YcPctwN5VXvtbpccPAA9UfZ+IiIjEVrJf5hAREZEEU5gQERGRqChMiIiISFQUJkRERCQqChMiIiISFYUJERERiYrChIiIiERFYUJERESiojAhIiIiUVGYEBERkagoTIiIiEhUFCZEREQkKgoTIiIiEhWFCREREYmKwoSIiIhERWFCREREoqIwISIiIlFRmBAREZGoKEyIiIhIVBQmREREJCoKEyIiIhIVhQkRERGJisKEiIiIREVhQkRERKKiMCEiIiJRUZgQERGRqChMiIiISFQUJkRERCQqChMiIiISFYUJERERiYrChIiIiERFYUJERESiojAhIiIiUVGYEBERkagoTIiIiEhUFCZEREQkKgoTIiIiEhWFCREREYmKwoSIiIhERWFCREREoqIwISIiIlFRmBAREZGoKEyIiIhIVBQmREREJCoKEyIiIhKVpA0TZrbEzD4xs4/MbHqY7WZmfzGzRWb2sZkdm4g6RUREUl1GoguIUpG7r42w7afAoaGvLsBfQ3+K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8PTT8JOfxL8+ERFpnNSZSALbt8PNNweTSn3ySeSpsC+4IOhGKEiIiEg8qTPRwM2YAf37B3dsRFqYa++9g4W5Tjop/vWJiIioM9FAbd0KV14JJ58cdBsidSMuvxwWLlSQEBGRxFFnogGaMgUGDID16yMvzHXAATB+PHTsGP/6REREKlNnogGYOBFmz4aNG2HIEOjRA1aurB4kdizMdd118OmnChIiItIwqDORYDNmQNeuweO99w5u9Yy0MNehhwYLcxUUxLdGERGRmqgzkUALF8JxoeVVcnNh3brqQSI9Pdh2221B8FCQEBGRhkadiQRZtSqYBhuC2SojTYXdsSOMGQMHHhjf+kRERGpLnYkEKCmB/ff//nnVFT4zM4PJpx54IBiMqSAhIiINmToTcVZWBr16QZMmsG1b9e25uXDkkfDvf8O++8a/PhERkbpSZyKOKiqCxbneead6kMjKCv7csgWmTQtmvRQREUkGChNx4h5MMPXyy+HnjthxqWPHbaEtW8a3PhERkV2lyxxx8pvfBAtw7RhomZ0dBIwWLYJbQseN050aIiKSnBQm4uDuu+H22yEjI5h0qlUrGDYMzj8/mMlSREQkmSlM1LP58+Gaa4LLFoMHw4UXBpNPiYiIpAqFiXpWUADz5gV/miW6GhERkdhTmKhnZnD44YmuQkREpP7obg4RERGJisJEHG3dupVTTz2V8vLyWu1/33330b59e4488kjuvffemNezYcMG+vXrx+GHH067du147733KC0t5ZRTTqGsrCzmnyciIqlJYSKORo8eTZ8+fUhPT9/pvnPmzOHRRx/lww8/ZPbs2bz88sssXLgwpvWMHDmSHj16MH/+fGbPnk27du3Iysqia9eujB8/PqafJSIiqUthIo7Gjh1Lr169arXvvHnz+NGPfkRubi4ZGRmceuqpvPjiizGrZePGjUyZMoWhQ4cCkJWVxR577AFA7969GTt2bMw+S0REUpvCRJyUlpayePFi2rRpU6v927dvz5QpU1i3bh1btmzh1VdfZdmyZTGrZ/HixeTn5zN48GA6duzIsGHD2Lx583efPW3atJh9loiIpDbdzREna9eu/e5f/gDdunVj9erV1fa79dZb6dWrF+3atePaa6/l9NNPJy8vj2OOOYaMjJ3/uGo67u677/7d87KyMmbOnMn9999Ply5dGDlyJHfccQe3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\n",
      "text/plain": [
       "<Figure size 576x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(figsize = (8, 8))\n",
    "#######################Arrows#######################\n",
    "arrows = np.array([[[0,0,3,2]],\n",
    "                   [[0,0,-9,-6]], \n",
    "                   [[0,0,6,4]]])\n",
    "colors = ['r','b','g']\n",
    "for i in range(arrows.shape[0]):\n",
    "    X,Y,U,V = zip(*arrows[i,:,:])\n",
    "    ax.arrow(X[0], Y[0], U[0],V[0], color = colors[i], width = .18, \n",
    "             length_includes_head = True,\n",
    "             head_width = .3, # default: 3*width\n",
    "             head_length = .6,\n",
    "             overhang = .4, zorder = -i)\n",
    "\n",
    "ax.scatter(0, 0, ec = 'red', fc = 'black', zorder = 5)\n",
    "ax.text(6, 4, '$(6, 4)$')\n",
    "ax.text(-9, -6.5, '$(-9, -6)$')\n",
    "ax.text(3, 2, '$(3, 2)$')\n",
    "\n",
    "ax.grid(True)\n",
    "ax.set_title('Linear Dependence Visualization')\n",
    "ax.axis([-10, 10, -10, 10])\n",
    "ax.set_xlabel('x-axis', size = 18)\n",
    "ax.set_ylabel('y-axis', size = 18)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Simply put, if one vector is the scalar multiple of the other, then these two vectors are linearly dependent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we visualize linear independence in $\\mathbb{R}^3$. There are three vectors $(1,-2,1)^T$, $(2,1,2)^T$, $(-1,2,3)^T$, plot them in $\\mathbb{R}^3$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The standard procedure is to write down the span of first two vectors, which is a plane. Then we check if the third vector is in the plane or not. If not, this set of vectors is linearly independent.\n",
    "\n",
    "$$\n",
    "\\left[\n",
    "\\begin{matrix}\n",
    "x\\\\\n",
    "y\\\\\n",
    "z\n",
    "\\end{matrix}\n",
    "\\right]=\n",
    "s\\left[\n",
    "\\begin{matrix}\n",
    "1\\\\\n",
    "-2\\\\\n",
    "1\n",
    "\\end{matrix}\n",
    "\\right]+\n",
    "t\\left[\n",
    "\\begin{matrix}\n",
    "2\\\\\n",
    "1\\\\\n",
    "2\n",
    "\\end{matrix}\n",
    "\\right]=\n",
    "\\left[\n",
    "\\begin{matrix}\n",
    "s+2t\\\\\n",
    "-2s+t\\\\\n",
    "s+2t\n",
    "\\end{matrix}\n",
    "\\right]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "/* Put everything inside the global mpl namespace */\n",
       "window.mpl = {};\n",
       "\n",
       "\n",
       "mpl.get_websocket_type = function() {\n",
       "    if (typeof(WebSocket) !== 'undefined') {\n",
       "        return WebSocket;\n",
       "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
       "        return MozWebSocket;\n",
       "    } else {\n",
       "        alert('Your browser does not have WebSocket support. ' +\n",
       "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
       "              'Firefox 4 and 5 are also supported but you ' +\n",
       "              'have to enable WebSockets in about:config.');\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
       "    this.id = figure_id;\n",
       "\n",
       "    this.ws = websocket;\n",
       "\n",
       "    this.supports_binary = (this.ws.binaryType != undefined);\n",
       "\n",
       "    if (!this.supports_binary) {\n",
       "        var warnings = document.getElementById(\"mpl-warnings\");\n",
       "        if (warnings) {\n",
       "            warnings.style.display = 'block';\n",
       "            warnings.textContent = (\n",
       "                \"This browser does not support binary websocket messages. \" +\n",
       "                    \"Performance may be slow.\");\n",
       "        }\n",
       "    }\n",
       "\n",
       "    this.imageObj = new Image();\n",
       "\n",
       "    this.context = undefined;\n",
       "    this.message = undefined;\n",
       "    this.canvas = undefined;\n",
       "    this.rubberband_canvas = undefined;\n",
       "    this.rubberband_context = undefined;\n",
       "    this.format_dropdown = undefined;\n",
       "\n",
       "    this.image_mode = 'full';\n",
       "\n",
       "    this.root = $('<div/>');\n",
       "    this._root_extra_style(this.root)\n",
       "    this.root.attr('style', 'display: inline-block');\n",
       "\n",
       "    $(parent_element).append(this.root);\n",
       "\n",
       "    this._init_header(this);\n",
       "    this._init_canvas(this);\n",
       "    this._init_toolbar(this);\n",
       "\n",
       "    var fig = this;\n",
       "\n",
       "    this.waiting = false;\n",
       "\n",
       "    this.ws.onopen =  function () {\n",
       "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
       "            fig.send_message(\"send_image_mode\", {});\n",
       "            if (mpl.ratio != 1) {\n",
       "                fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
       "            }\n",
       "            fig.send_message(\"refresh\", {});\n",
       "        }\n",
       "\n",
       "    this.imageObj.onload = function() {\n",
       "            if (fig.image_mode == 'full') {\n",
       "                // Full images could contain transparency (where diff images\n",
       "                // almost always do), so we need to clear the canvas so that\n",
       "                // there is no ghosting.\n",
       "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
       "            }\n",
       "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
       "        };\n",
       "\n",
       "    this.imageObj.onunload = function() {\n",
       "        fig.ws.close();\n",
       "    }\n",
       "\n",
       "    this.ws.onmessage = this._make_on_message_function(this);\n",
       "\n",
       "    this.ondownload = ondownload;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_header = function() {\n",
       "    var titlebar = $(\n",
       "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
       "        'ui-helper-clearfix\"/>');\n",
       "    var titletext = $(\n",
       "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
       "        'text-align: center; padding: 3px;\"/>');\n",
       "    titlebar.append(titletext)\n",
       "    this.root.append(titlebar);\n",
       "    this.header = titletext[0];\n",
       "}\n",
       "\n",
       "\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_canvas = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var canvas_div = $('<div/>');\n",
       "\n",
       "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
       "\n",
       "    function canvas_keyboard_event(event) {\n",
       "        return fig.key_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
       "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
       "    this.canvas_div = canvas_div\n",
       "    this._canvas_extra_style(canvas_div)\n",
       "    this.root.append(canvas_div);\n",
       "\n",
       "    var canvas = $('<canvas/>');\n",
       "    canvas.addClass('mpl-canvas');\n",
       "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
       "\n",
       "    this.canvas = canvas[0];\n",
       "    this.context = canvas[0].getContext(\"2d\");\n",
       "\n",
       "    var backingStore = this.context.backingStorePixelRatio ||\n",
       "\tthis.context.webkitBackingStorePixelRatio ||\n",
       "\tthis.context.mozBackingStorePixelRatio ||\n",
       "\tthis.context.msBackingStorePixelRatio ||\n",
       "\tthis.context.oBackingStorePixelRatio ||\n",
       "\tthis.context.backingStorePixelRatio || 1;\n",
       "\n",
       "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
       "\n",
       "    var rubberband = $('<canvas/>');\n",
       "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
       "\n",
       "    var pass_mouse_events = true;\n",
       "\n",
       "    canvas_div.resizable({\n",
       "        start: function(event, ui) {\n",
       "            pass_mouse_events = false;\n",
       "        },\n",
       "        resize: function(event, ui) {\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "        stop: function(event, ui) {\n",
       "            pass_mouse_events = true;\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "    });\n",
       "\n",
       "    function mouse_event_fn(event) {\n",
       "        if (pass_mouse_events)\n",
       "            return fig.mouse_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    rubberband.mousedown('button_press', mouse_event_fn);\n",
       "    rubberband.mouseup('button_release', mouse_event_fn);\n",
       "    // Throttle sequential mouse events to 1 every 20ms.\n",
       "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
       "\n",
       "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
       "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
       "\n",
       "    canvas_div.on(\"wheel\", function (event) {\n",
       "        event = event.originalEvent;\n",
       "        event['data'] = 'scroll'\n",
       "        if (event.deltaY < 0) {\n",
       "            event.step = 1;\n",
       "        } else {\n",
       "            event.step = -1;\n",
       "        }\n",
       "        mouse_event_fn(event);\n",
       "    });\n",
       "\n",
       "    canvas_div.append(canvas);\n",
       "    canvas_div.append(rubberband);\n",
       "\n",
       "    this.rubberband = rubberband;\n",
       "    this.rubberband_canvas = rubberband[0];\n",
       "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
       "    this.rubberband_context.strokeStyle = \"#000000\";\n",
       "\n",
       "    this._resize_canvas = function(width, height) {\n",
       "        // Keep the size of the canvas, canvas container, and rubber band\n",
       "        // canvas in synch.\n",
       "        canvas_div.css('width', width)\n",
       "        canvas_div.css('height', height)\n",
       "\n",
       "        canvas.attr('width', width * mpl.ratio);\n",
       "        canvas.attr('height', height * mpl.ratio);\n",
       "        canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
       "\n",
       "        rubberband.attr('width', width);\n",
       "        rubberband.attr('height', height);\n",
       "    }\n",
       "\n",
       "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
       "    // upon first draw.\n",
       "    this._resize_canvas(600, 600);\n",
       "\n",
       "    // Disable right mouse context menu.\n",
       "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
       "        return false;\n",
       "    });\n",
       "\n",
       "    function set_focus () {\n",
       "        canvas.focus();\n",
       "        canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    window.setTimeout(set_focus, 100);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>');\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items) {\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) {\n",
       "            // put a spacer in here.\n",
       "            continue;\n",
       "        }\n",
       "        var button = $('<button/>');\n",
       "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
       "                        'ui-button-icon-only');\n",
       "        button.attr('role', 'button');\n",
       "        button.attr('aria-disabled', 'false');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "\n",
       "        var icon_img = $('<span/>');\n",
       "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
       "        icon_img.addClass(image);\n",
       "        icon_img.addClass('ui-corner-all');\n",
       "\n",
       "        var tooltip_span = $('<span/>');\n",
       "        tooltip_span.addClass('ui-button-text');\n",
       "        tooltip_span.html(tooltip);\n",
       "\n",
       "        button.append(icon_img);\n",
       "        button.append(tooltip_span);\n",
       "\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    var fmt_picker_span = $('<span/>');\n",
       "\n",
       "    var fmt_picker = $('<select/>');\n",
       "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
       "    fmt_picker_span.append(fmt_picker);\n",
       "    nav_element.append(fmt_picker_span);\n",
       "    this.format_dropdown = fmt_picker[0];\n",
       "\n",
       "    for (var ind in mpl.extensions) {\n",
       "        var fmt = mpl.extensions[ind];\n",
       "        var option = $(\n",
       "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
       "        fmt_picker.append(option);\n",
       "    }\n",
       "\n",
       "    // Add hover states to the ui-buttons\n",
       "    $( \".ui-button\" ).hover(\n",
       "        function() { $(this).addClass(\"ui-state-hover\");},\n",
       "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
       "    );\n",
       "\n",
       "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
       "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
       "    // which will in turn request a refresh of the image.\n",
       "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_message = function(type, properties) {\n",
       "    properties['type'] = type;\n",
       "    properties['figure_id'] = this.id;\n",
       "    this.ws.send(JSON.stringify(properties));\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_draw_message = function() {\n",
       "    if (!this.waiting) {\n",
       "        this.waiting = true;\n",
       "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
       "    }\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    var format_dropdown = fig.format_dropdown;\n",
       "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
       "    fig.ondownload(fig, format);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
       "    var size = msg['size'];\n",
       "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
       "        fig._resize_canvas(size[0], size[1]);\n",
       "        fig.send_message(\"refresh\", {});\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
       "    var x0 = msg['x0'] / mpl.ratio;\n",
       "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
       "    var x1 = msg['x1'] / mpl.ratio;\n",
       "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
       "    x0 = Math.floor(x0) + 0.5;\n",
       "    y0 = Math.floor(y0) + 0.5;\n",
       "    x1 = Math.floor(x1) + 0.5;\n",
       "    y1 = Math.floor(y1) + 0.5;\n",
       "    var min_x = Math.min(x0, x1);\n",
       "    var min_y = Math.min(y0, y1);\n",
       "    var width = Math.abs(x1 - x0);\n",
       "    var height = Math.abs(y1 - y0);\n",
       "\n",
       "    fig.rubberband_context.clearRect(\n",
       "        0, 0, fig.canvas.width / mpl.ratio, fig.canvas.height / mpl.ratio);\n",
       "\n",
       "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
       "    // Updates the figure title.\n",
       "    fig.header.textContent = msg['label'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
       "    var cursor = msg['cursor'];\n",
       "    switch(cursor)\n",
       "    {\n",
       "    case 0:\n",
       "        cursor = 'pointer';\n",
       "        break;\n",
       "    case 1:\n",
       "        cursor = 'default';\n",
       "        break;\n",
       "    case 2:\n",
       "        cursor = 'crosshair';\n",
       "        break;\n",
       "    case 3:\n",
       "        cursor = 'move';\n",
       "        break;\n",
       "    }\n",
       "    fig.rubberband_canvas.style.cursor = cursor;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
       "    fig.message.textContent = msg['message'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
       "    // Request the server to send over a new figure.\n",
       "    fig.send_draw_message();\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
       "    fig.image_mode = msg['mode'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Called whenever the canvas gets updated.\n",
       "    this.send_message(\"ack\", {});\n",
       "}\n",
       "\n",
       "// A function to construct a web socket function for onmessage handling.\n",
       "// Called in the figure constructor.\n",
       "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
       "    return function socket_on_message(evt) {\n",
       "        if (evt.data instanceof Blob) {\n",
       "            /* FIXME: We get \"Resource interpreted as Image but\n",
       "             * transferred with MIME type text/plain:\" errors on\n",
       "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
       "             * to be part of the websocket stream */\n",
       "            evt.data.type = \"image/png\";\n",
       "\n",
       "            /* Free the memory for the previous frames */\n",
       "            if (fig.imageObj.src) {\n",
       "                (window.URL || window.webkitURL).revokeObjectURL(\n",
       "                    fig.imageObj.src);\n",
       "            }\n",
       "\n",
       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
       "                evt.data);\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
       "            fig.imageObj.src = evt.data;\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        var msg = JSON.parse(evt.data);\n",
       "        var msg_type = msg['type'];\n",
       "\n",
       "        // Call the  \"handle_{type}\" callback, which takes\n",
       "        // the figure and JSON message as its only arguments.\n",
       "        try {\n",
       "            var callback = fig[\"handle_\" + msg_type];\n",
       "        } catch (e) {\n",
       "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        if (callback) {\n",
       "            try {\n",
       "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
       "                callback(fig, msg);\n",
       "            } catch (e) {\n",
       "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
       "            }\n",
       "        }\n",
       "    };\n",
       "}\n",
       "\n",
       "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
       "mpl.findpos = function(e) {\n",
       "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
       "    var targ;\n",
       "    if (!e)\n",
       "        e = window.event;\n",
       "    if (e.target)\n",
       "        targ = e.target;\n",
       "    else if (e.srcElement)\n",
       "        targ = e.srcElement;\n",
       "    if (targ.nodeType == 3) // defeat Safari bug\n",
       "        targ = targ.parentNode;\n",
       "\n",
       "    // jQuery normalizes the pageX and pageY\n",
       "    // pageX,Y are the mouse positions relative to the document\n",
       "    // offset() returns the position of the element relative to the document\n",
       "    var x = e.pageX - $(targ).offset().left;\n",
       "    var y = e.pageY - $(targ).offset().top;\n",
       "\n",
       "    return {\"x\": x, \"y\": y};\n",
       "};\n",
       "\n",
       "/*\n",
       " * return a copy of an object with only non-object keys\n",
       " * we need this to avoid circular references\n",
       " * http://stackoverflow.com/a/24161582/3208463\n",
       " */\n",
       "function simpleKeys (original) {\n",
       "  return Object.keys(original).reduce(function (obj, key) {\n",
       "    if (typeof original[key] !== 'object')\n",
       "        obj[key] = original[key]\n",
       "    return obj;\n",
       "  }, {});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.mouse_event = function(event, name) {\n",
       "    var canvas_pos = mpl.findpos(event)\n",
       "\n",
       "    if (name === 'button_press')\n",
       "    {\n",
       "        this.canvas.focus();\n",
       "        this.canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    var x = canvas_pos.x * mpl.ratio;\n",
       "    var y = canvas_pos.y * mpl.ratio;\n",
       "\n",
       "    this.send_message(name, {x: x, y: y, button: event.button,\n",
       "                             step: event.step,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "\n",
       "    /* This prevents the web browser from automatically changing to\n",
       "     * the text insertion cursor when the button is pressed.  We want\n",
       "     * to control all of the cursor setting manually through the\n",
       "     * 'cursor' event from matplotlib */\n",
       "    event.preventDefault();\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    // Handle any extra behaviour associated with a key event\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.key_event = function(event, name) {\n",
       "\n",
       "    // Prevent repeat events\n",
       "    if (name == 'key_press')\n",
       "    {\n",
       "        if (event.which === this._key)\n",
       "            return;\n",
       "        else\n",
       "            this._key = event.which;\n",
       "    }\n",
       "    if (name == 'key_release')\n",
       "        this._key = null;\n",
       "\n",
       "    var value = '';\n",
       "    if (event.ctrlKey && event.which != 17)\n",
       "        value += \"ctrl+\";\n",
       "    if (event.altKey && event.which != 18)\n",
       "        value += \"alt+\";\n",
       "    if (event.shiftKey && event.which != 16)\n",
       "        value += \"shift+\";\n",
       "\n",
       "    value += 'k';\n",
       "    value += event.which.toString();\n",
       "\n",
       "    this._key_event_extra(event, name);\n",
       "\n",
       "    this.send_message(name, {key: value,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
       "    if (name == 'download') {\n",
       "        this.handle_save(this, null);\n",
       "    } else {\n",
       "        this.send_message(\"toolbar_button\", {name: name});\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
       "    this.message.textContent = tooltip;\n",
       "};\n",
       "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
       "\n",
       "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
       "\n",
       "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
       "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
       "    // object with the appropriate methods. Currently this is a non binary\n",
       "    // socket, so there is still some room for performance tuning.\n",
       "    var ws = {};\n",
       "\n",
       "    ws.close = function() {\n",
       "        comm.close()\n",
       "    };\n",
       "    ws.send = function(m) {\n",
       "        //console.log('sending', m);\n",
       "        comm.send(m);\n",
       "    };\n",
       "    // Register the callback with on_msg.\n",
       "    comm.on_msg(function(msg) {\n",
       "        //console.log('receiving', msg['content']['data'], msg);\n",
       "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
       "        ws.onmessage(msg['content']['data'])\n",
       "    });\n",
       "    return ws;\n",
       "}\n",
       "\n",
       "mpl.mpl_figure_comm = function(comm, msg) {\n",
       "    // This is the function which gets called when the mpl process\n",
       "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
       "\n",
       "    var id = msg.content.data.id;\n",
       "    // Get hold of the div created by the display call when the Comm\n",
       "    // socket was opened in Python.\n",
       "    var element = $(\"#\" + id);\n",
       "    var ws_proxy = comm_websocket_adapter(comm)\n",
       "\n",
       "    function ondownload(figure, format) {\n",
       "        window.open(figure.imageObj.src);\n",
       "    }\n",
       "\n",
       "    var fig = new mpl.figure(id, ws_proxy,\n",
       "                           ondownload,\n",
       "                           element.get(0));\n",
       "\n",
       "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
       "    // web socket which is closed, not our websocket->open comm proxy.\n",
       "    ws_proxy.onopen();\n",
       "\n",
       "    fig.parent_element = element.get(0);\n",
       "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
       "    if (!fig.cell_info) {\n",
       "        console.error(\"Failed to find cell for figure\", id, fig);\n",
       "        return;\n",
       "    }\n",
       "\n",
       "    var output_index = fig.cell_info[2]\n",
       "    var cell = fig.cell_info[0];\n",
       "\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
       "    var width = fig.canvas.width/mpl.ratio\n",
       "    fig.root.unbind('remove')\n",
       "\n",
       "    // Update the output cell to use the data from the current canvas.\n",
       "    fig.push_to_output();\n",
       "    var dataURL = fig.canvas.toDataURL();\n",
       "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
       "    // the notebook keyboard shortcuts fail.\n",
       "    IPython.keyboard_manager.enable()\n",
       "    $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
       "    fig.close_ws(fig, msg);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.close_ws = function(fig, msg){\n",
       "    fig.send_message('closing', msg);\n",
       "    // fig.ws.close()\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
       "    // Turn the data on the canvas into data in the output cell.\n",
       "    var width = this.canvas.width/mpl.ratio\n",
       "    var dataURL = this.canvas.toDataURL();\n",
       "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Tell IPython that the notebook contents must change.\n",
       "    IPython.notebook.set_dirty(true);\n",
       "    this.send_message(\"ack\", {});\n",
       "    var fig = this;\n",
       "    // Wait a second, then push the new image to the DOM so\n",
       "    // that it is saved nicely (might be nice to debounce this).\n",
       "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>');\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items){\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) { continue; };\n",
       "\n",
       "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    // Add the status bar.\n",
       "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "\n",
       "    // Add the close button to the window.\n",
       "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
       "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
       "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
       "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
       "    buttongrp.append(button);\n",
       "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
       "    titlebar.prepend(buttongrp);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(el){\n",
       "    var fig = this\n",
       "    el.on(\"remove\", function(){\n",
       "\tfig.close_ws(fig, {});\n",
       "    });\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(el){\n",
       "    // this is important to make the div 'focusable\n",
       "    el.attr('tabindex', 0)\n",
       "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
       "    // off when our div gets focus\n",
       "\n",
       "    // location in version 3\n",
       "    if (IPython.notebook.keyboard_manager) {\n",
       "        IPython.notebook.keyboard_manager.register_events(el);\n",
       "    }\n",
       "    else {\n",
       "        // location in version 2\n",
       "        IPython.keyboard_manager.register_events(el);\n",
       "    }\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    var manager = IPython.notebook.keyboard_manager;\n",
       "    if (!manager)\n",
       "        manager = IPython.keyboard_manager;\n",
       "\n",
       "    // Check for shift+enter\n",
       "    if (event.shiftKey && event.which == 13) {\n",
       "        this.canvas_div.blur();\n",
       "        // select the cell after this one\n",
       "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
       "        IPython.notebook.select(index + 1);\n",
       "    }\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    fig.ondownload(fig, null);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.find_output_cell = function(html_output) {\n",
       "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
       "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
       "    // IPython event is triggered only after the cells have been serialised, which for\n",
       "    // our purposes (turning an active figure into a static one), is too late.\n",
       "    var cells = IPython.notebook.get_cells();\n",
       "    var ncells = cells.length;\n",
       "    for (var i=0; i<ncells; i++) {\n",
       "        var cell = cells[i];\n",
       "        if (cell.cell_type === 'code'){\n",
       "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
       "                var data = cell.output_area.outputs[j];\n",
       "                if (data.data) {\n",
       "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
       "                    data = data.data;\n",
       "                }\n",
       "                if (data['text/html'] == html_output) {\n",
       "                    return [cell, data, j];\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "}\n",
       "\n",
       "// Register the function which deals with the matplotlib target/channel.\n",
       "// The kernel may be null if the page has been refreshed.\n",
       "if (IPython.notebook.kernel != null) {\n",
       "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
       "}\n"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<img src=\"\" width=\"800\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib notebook\n",
    "\n",
    "fig = plt.figure(figsize = (8,8))\n",
    "ax = fig.add_subplot(projection='3d')\n",
    "\n",
    "s = np.linspace(-1, 1, 10)\n",
    "t = np.linspace(-1, 1, 10)\n",
    "S, T = np.meshgrid(s, t)\n",
    "\n",
    "X = S+2*T\n",
    "Y = -2*S+T\n",
    "Z = S+2*T\n",
    "ax.plot_wireframe(X, Y, Z, linewidth = 1.5, color = 'k', alpha = .6)\n",
    "\n",
    "vec = np.array([[[0, 0, 0, 1, -2, 1]],\n",
    "               [[0, 0, 0, 2, 1, 2]],\n",
    "               [[0, 0, 0, -1, 2, 3]]])\n",
    "colors = ['r','b','g']\n",
    "for i in range(vec.shape[0]):\n",
    "    X, Y, Z, U, V, W = zip(*vec[i,:,:])\n",
    "    ax.quiver(X, Y, Z, U, V, W, length=1, normalize=False, color = colors[i],\n",
    "              arrow_length_ratio = .08, pivot = 'tail',\n",
    "              linestyles = 'solid',linewidths = 3, alpha = .6)\n",
    "\n",
    "ax.set_title('Linear Independence Visualization')\n",
    "\n",
    "ax.set_xlabel('x-axis', size = 18)\n",
    "ax.set_ylabel('y-axis', size = 18)\n",
    "ax.set_zlabel('z-axis', size = 18)\n",
    "\n",
    "ax.view_init(elev=20., azim=120)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pan around the image, we can see that the <font face=\"gotham\" color=\"green\">green</font> vector is not in the plane spanned by red and blue vector, thus they are linearly independent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font face=\"gotham\" color=\"red\"> A Side Note for Linear Dependence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let $S = \\{{v}_1,{v}_2,{v}_3, ..., {v}_n\\}$ be a set of vectors in $\\mathbb{R}^m$, if $n>m$, then $S$ is linearly dependent. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It means the there must be at least one vector in the <font face=\"gotham\" color=\"red\">vector space</font> spanned by the rest of vectors. For instance, a matrix $A$ which has 4 columns and 3 rows, then its columns are linear dependent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Also if $S = \\{{v}_1,{v}_2,{v}_3, ..., {v}_n\\}$ contains a zero vector, then the set is linearly dependent as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
